package Part3_泛型的继承和通配符;

import Part1_泛型的使用.BirthDay;
import Part1_泛型的使用.Boss;
import Part1_泛型的使用.Employee;
import Part1_泛型的使用.Person;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * ClassName: Demo
 * Package: IntelliJ IDEA
 * Description:
 * Written by HanXu
 * Create 2024.04.17 17:47
 */
public class Demo {
    @Test
    public void test1(){

        List<Object> list1 = null;
        List<String> list2 = null;
        List<?>      list3 = null;

        print(list1);
        print(list2);
        print(list3);

        //可以赋值，类似继承
        list3 = list1;
        print(list3);

        //可以赋值，类似继承
        list3 = list2;
        print(list3);
    }

    @Test
    public void test2(){
        /*
         *  通配符：？
         *  ? extends A:
         *  ? super B:
         * */

        //要求传入的泛型需继承自Object类
        List<?> list1 = new ArrayList<>();
        //要求传入的泛型需是Person的父类
        List<? super Person> list2 = new ArrayList<>();
        //要求传入的泛型需是Employee的父类
        List<? super Employee> list5 = new ArrayList<>();

        List<Employee> list3 = new ArrayList<>();
        List<Person> list4 = new ArrayList<>();

        list1 = list3;
        list2 = list4;//同类OK
        list5 = list3;//同类OK

        //可以的话泛型没有意义了
        //list4 = list3;

        //错误：Employee是Person子类
        //list2 = list3;
    }

    @Test
    public void test3(){
        List<? extends Employee> list1 = new ArrayList<>();
        List<Employee> list2 = new ArrayList<>();
        list2.add(new Employee("Tom",new BirthDay(1999,2,3)));

        //读数据
        list1 = list2;
        System.out.println(list1.get(0));//list1可读

        //写数据
        //list1不可写
        //list1.add(new Employee("CC",new BirthDay(1999,3,2)));
        //例外：null
        list1.add(null);
    }


    @Test
    public void test4(){
        List<? super Employee> list1 = new ArrayList<>();
        List<Employee> list2 = new ArrayList<>();
        list2.add(new Employee("Tom",new BirthDay(1999,2,3)));

        //读数据
        list1 = list2;
        System.out.println(list1.get(0));//list1可读

        //写数据
        //list1可写
        //用数轴来理解：add的对象不能大于Employee，因为如果大于Employee就可能大于通配符可能的类型（向父类的方法为正）
        list1.add(new Employee("CC",new BirthDay(1999,3,2)));
        //Boss为Employee子类，一定小于通配符可能的类型，可以被接受
        list1.add(new Boss("AA",new BirthDay(1980,4,30)));

        //例外
        //new Object()对象的类为正无穷（向父类的方法为正）
        //list1.add(new Object());
    }


    //使用通配符增加方法（形参传入）的兼容性
    public void print(List<?> list){
        for(Object object : list){
            System.out.println(object);
        }
    }
}
